package com.shuda.business.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shuda.business.user.dto.LoginDTO;
import com.shuda.business.user.dto.RegisterDTO;
import com.shuda.business.user.entity.UserEntity;
import com.shuda.business.user.mapper.UserMapper;
import com.shuda.business.user.service.AuthService;
import com.shuda.common.dto.UserProfileDTO;
import com.shuda.common.exception.BusinessException;
import com.shuda.common.dto.ChangePasswordDTO;
import com.shuda.common.dto.UserProfileDTO;
import com.shuda.common.result.Result;
import com.shuda.common.security.JwtTokenProvider;
import com.shuda.common.utils.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 */
@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final UserMapper userMapper;
    private final AuthenticationManager authenticationManager;
    private final JwtTokenProvider tokenProvider;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public Map<String, Object> login(LoginDTO loginDTO) {
        // 验证验证码
        String cacheCode = redisTemplate.opsForValue().get("captcha:" + loginDTO.getUuid());
        if (cacheCode == null || !cacheCode.equals(loginDTO.getCaptcha())) {
            throw new BusinessException("验证码错误或已过期");
        }

        // 删除验证码
        redisTemplate.delete("captcha:" + loginDTO.getUuid());

        try {
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginDTO.getUsername(),
                            loginDTO.getPassword()
                    )
            );

            SecurityContextHolder.getContext().setAuthentication(authentication);
            String accessToken = tokenProvider.generateAccessToken(authentication.getName());
            String refreshToken = tokenProvider.generateRefreshToken(authentication.getName());

            // 保存刷新token到redis
            redisTemplate.opsForValue().set("refresh_token:" + authentication.getName(), refreshToken,
                    tokenProvider.getRefreshTokenExpiration(), java.util.concurrent.TimeUnit.SECONDS);

            Map<String, Object> result = new HashMap<>();
            result.put("accessToken", accessToken);
            result.put("refreshToken", refreshToken);
            result.put("tokenType", "Bearer");

            return result;
        } catch (Exception e) {
            throw new BusinessException("用户名或密码错误");
        }
    }

    @Override
    public Result<String> register(RegisterDTO registerDTO) {
        // 检查用户名是否已存在
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUsername, registerDTO.getUsername());
        if (userMapper.selectCount(wrapper) > 0) {
            return Result.failed("用户名已存在");
        }

        // 创建新用户
        UserEntity user = new UserEntity();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        user.setNickname(registerDTO.getNickname());
        user.setEmail(registerDTO.getEmail());
        user.setPhone(registerDTO.getPhone());
        user.setStatus(1); // 启用状态
        userMapper.insert(user);

        return Result.success("注册成功");
    }

    @Override
    public void logout() {
        String username = SecurityUtils.getCurrentUsername();
        // 删除redis中的刷新token
        redisTemplate.delete("refresh_token:" + username);
        // 清除SecurityContext
        SecurityContextHolder.clearContext();
    }

    @Override
    public Map<String, Object> refreshToken(String refreshToken) {
        // 验证刷新token
        String username = tokenProvider.getUsernameFromToken(refreshToken);
        String cacheRefreshToken = redisTemplate.opsForValue().get("refresh_token:" + username);
        
        if (cacheRefreshToken == null || !cacheRefreshToken.equals(refreshToken)) {
            throw new BusinessException("刷新token无效");
        }

        // 验证刷新token是否过期
        if (!tokenProvider.validateToken(refreshToken)) {
            throw new BusinessException("刷新token已过期");
        }

        // 生成新的访问token
        String newAccessToken = tokenProvider.generateAccessToken(username);
        String newRefreshToken = tokenProvider.generateRefreshToken(username);

        // 更新redis中的刷新token
        redisTemplate.opsForValue().set("refresh_token:" + username, newRefreshToken,
                tokenProvider.getRefreshTokenExpiration(), java.util.concurrent.TimeUnit.SECONDS);

        Map<String, Object> result = new HashMap<>();
        result.put("accessToken", newAccessToken);
        result.put("refreshToken", newRefreshToken);
        result.put("tokenType", "Bearer");
        return result;
    }

    @Override
    public UserEntity getUserInfo() {
        String username = SecurityUtils.getCurrentUsername();
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUsername, username);
        UserEntity user = userMapper.selectOne(wrapper);
        
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        return user;
    }

    @Override
    public UserProfileDTO getProfile() {
        UserEntity user = getUserInfo();
        UserProfileDTO profile = new UserProfileDTO();
        profile.setUsername(user.getUsername());
        profile.setNickname(user.getNickname());
        profile.setRealName(user.getRealName());
        profile.setEmail(user.getEmail());
        profile.setPhone(user.getPhone());
        profile.setRemark(user.getRemark());
        return profile;
    }

    @Override
    @Transactional
    public void updateProfile(UserProfileDTO profileDTO) {
        String username = SecurityUtils.getCurrentUsername();
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUsername, username);
        UserEntity user = userMapper.selectOne(wrapper);

        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        user.setNickname(profileDTO.getNickname());
        user.setRealName(profileDTO.getRealName());
        user.setEmail(profileDTO.getEmail());
        user.setPhone(profileDTO.getPhone());
        user.setRemark(profileDTO.getRemark());

        userMapper.updateById(user);
    }

    @Override
    @Transactional
    public void changePassword(ChangePasswordDTO changePasswordDTO) {
        String username = SecurityUtils.getCurrentUsername();
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUsername, username);
        UserEntity user = userMapper.selectOne(wrapper);

        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (!passwordEncoder.matches(changePasswordDTO.getOldPassword(), user.getPassword())) {
            throw new BusinessException("旧密码错误");
        }

        if (!changePasswordDTO.getNewPassword().equals(changePasswordDTO.getConfirmPassword())) {
            throw new BusinessException("新密码与确认密码不一致");
        }

        user.setPassword(passwordEncoder.encode(changePasswordDTO.getNewPassword()));
        userMapper.updateById(user);
    }



    
}